
//--> Loth 2011 
//--> camera systeme fps & rotation

package chamans.away
{
	import away3d.cameras.*;
	import away3d.cameras.lenses.*;
	import away3d.containers.*;
	import away3d.entities.*;
	import away3d.events.*;
	import away3d.materials.*;
	import away3d.primitives.*;
	
 	import com.greensock.*;
 	import com.greensock.easing.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.net.*;
	import flash.ui.*;
	import flash.utils.*;
	public class cameralo extends Camera3D
	{
		public function cameralo(base:Object, fov:int=45, far:int=4000 , near:int=1):void
		{
			BASE=base
			M = { 
				type:"normal",
				V:90, H:90, distance:600, posY:90,
				lastPos:new Point(0,0), lastAxe:new Point(0,0), 
				minX:0, maxX:0, maxY:170, minY:10,  maxZ:10000, minZ:1, 
				actif:false , move:false, camSpring:false, //moveY:false,
				
				baseTarget: new Vector3D(0,0,0),
				camTarget: new Vector3D(),
				camPos: new Vector3D(),
				/// special fps viseur
				Vdistance:0,  Vangle:0,  Vaxe:new Point(0,0),  gun:false,
				gunTarget: new Vector3D(0,0,0),
				gunPosition: new Vector3D(0,0,0)
			};
			create( fov, far , near )
		} 
		private function create( fov:int, far:int, near:int):void
		{
			BASE.view.camera.lens.fieldOfView = fov
			BASE.view.camera.lens.far = far;
			BASE.view.camera.lens.near = near;
			if(M.type=="normal"){
				BASE.stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseZoom, false, 0, true );
				BASE.stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown, false, 0, true );
			}}
		
		//______________________________________updateFrame fonction
		public function update( ):void
		{
			if (!target)autoTarget()
			if (planTop)planTop.update()
			if(M.type=="normal"){
				if(M.actif) mouseAxis();	
				if(factor==0) M.camTarget=target.position.add(M.baseTarget) 
				else M.camTarget= (new Vector3D(target.position.x*factor, target.position.y*factor, target.position.z*factor) ).add(M.baseTarget) 
				BASE.view.camera.position=(Orbit(M.H, M.V, M.distance)).add(M.camTarget)
				BASE.view.camera.lookAt(M.camTarget)
			}
			else {
				AutoMove();
				BASE.view.camera.position=M.baseTarget
				M.camTarget=(Orbit(M.H+180, -M.V, -M.distance)).add(M.baseTarget)
				target.position= M.camTarget
				BASE.view.camera.lookAt(M.camTarget)
				Add_GUN( )
		}}	
		
		//______________________________________Gun shoot
		public function Add_GUN( ):void
		{
			if(!M.gun){
				M.gun=true;
				newGUN();
			}
			GUN.position=M.baseTarget;
			var factor:Number=4;
			if(mouseback){M.gunTarget=(new Vector3D(-M.Vaxe.x*factor, M.Vaxe.y*factor, M.distance ))}
			GUN.rotationX=M.H+90;
			GUN.rotationY=M.V-90;
			M.cible.position=M.gunTarget;
		}
		private function newGUN():void 
		{
			var cib:ColorMaterial = new ColorMaterial(0xFFFFFF, 0);
			var cible:Sprite3D=new Sprite3D(cib , 100, 100);
		
			GUN= new ObjectContainer3D()
			BASE.view.scene.addChild(GUN)
		//	GUNin= new ObjectContainer3D()
			M.gunPosition=new Vector3D(-22, -15, -100)
			M.cible=cible;
			GUN.addChild(cible);
		}
		
		//______________________________________rotation & zoom normal type
		private function onDown(event:MouseEvent):void 
		{
			M.actif=true;
			M.lastAxe = new Point( M.V, M.H );
			M.lastPos = new Point( BASE.stage.mouseX, BASE.stage.mouseY );
			BASE.stage.removeEventListener( MouseEvent.MOUSE_DOWN, onDown );
			BASE.stage.addEventListener( MouseEvent.MOUSE_UP, onUp, false, 0, true );
		}
		private function autoTarget() :void
		{ 
			target=new ObjectContainer3D()
			BASE.view.scene.addChild(target)
		}
		private function onUp(e:Event) :void
		{
			M.actif=false;
			BASE.stage.removeEventListener( MouseEvent.MOUSE_UP, onUp);
			BASE.stage.addEventListener( MouseEvent.MOUSE_DOWN, onDown, false, 0, true);
		}
		private function AutoMove(e:Event=null):void 
		{
			
			if(BASE.autoMove && !BASE.MenuActif ) {
				VISORteste()
				mouseAxis();
				if(planTop)planTop.rotate()
			}}
		//______________________________________rotation & zoom fps type
		private function VISORteste():void{
			var centre:Point=new Point(BASE.size.x>>1, BASE.size.y>>1)
			var Mousepos:Point= new Point(BASE.stage.mouseX, BASE.stage.mouseY)
			var angle:Number=Math.atan2(Mousepos.y-centre.y,Mousepos.x-centre.x);
			M.Vrotation=Rad_Deg(angle)>>0
			M.Vdistance=Math.sqrt(Math.pow((Mousepos.x-centre.x),2)+Math.pow((Mousepos.y-centre.y),2))>>0;
			M.Vaxe.x=(M.Vdistance*Math.cos(angle))>>0// position axe X
			M.Vaxe.y=(M.Vdistance*Math.sin(angle))>>0// position axe Y
		}
		public function Deg_Rad(d:Number):Number{ return(d * Math.PI / 180) }
		public function Rad_Deg(d:Number):Number{ return(d * 180 / Math.PI) }
		
		private function mouseAxis(e:Event=null):void 
		{
			if(M.type=="normal"){
				M.V =((( BASE.stage.mouseX - M.lastPos.x)>>1) )+ M.lastAxe.x
				M.H =((( BASE.stage.mouseY - M.lastPos.y)>>1) )+ M.lastAxe.y
			}
			else {// fps
				if(mouseback){
					var lx:int=(BASE.size.x-60)>>1
					var ly:int=(BASE.size.y-130)>>1
					if(M.Vaxe.y<ly && M.Vaxe.y>-ly && M.Vaxe.x<lx && M.Vaxe.x>-lx){
						moveCursor()
						var maxi:Number=200
						if(M.Vdistance>30){
							if(M.Vaxe.x>maxi) M.Vaxe.x=maxi
							if(M.Vaxe.y>maxi) M.Vaxe.y=maxi
							if(M.Vaxe.x<-maxi) M.Vaxe.x=-maxi
							if(M.Vaxe.y<-maxi) M.Vaxe.y=-maxi
							
							M.V+=((M.Vaxe.x)/100)	
							M.H+=((M.Vaxe.y)/100)
						}}
					else{
						recentreCursor()
					}}
			}
			if(M.H < M.minY) M.H=M.minY; 	
			if(M.H > M.maxY) M.H=M.maxY;
		}
		private function recentreCursor():void 
		{
			mouseback=false
			var px:int=BASE.size.x>>1
			var py:int=BASE.size.y>>1
			M.POY=new Point(M.V, M.H)
			TweenNano.to(BASE.SYS.viseur, .6, {x:px, y:py, onComplete:onCompleteCursor,  ease:Expo.easeIn });	
			TweenNano.to(M.POY, .6, {x:90, y:90, ease:Expo.easeIn , onUpdate:onUpView});
			TweenNano.to(M.gunTarget, .6, {x:0, y:0, ease:Expo.easeIn , onUpdate:onUpView});
		}
		private function onUpView():void 
		{  
			M.H=M.POY.y;
		}
		private function onCompleteCursor():void 
		{   
			BASE.SYS.cible_retour()
			BASE.SYS.addEventListener(Event.ENTER_FRAME,checkRetourCursor)
		}
		private function checkRetourCursor(e:Event):void 
		{ 
			if(M.Vdistance<60){
				BASE.SYS.removeEventListener(Event.ENTER_FRAME,checkRetourCursor)
				BASE.SYS.cible_retour(false)
				mouseback=true	
			}}
		private function moveCursor():void 
		{
		//	BASE.SYS.viseur.x=O.stage.mouseX
		//	BASE.SYS.viseur.y=O.stage.mouseY
		}
		private function mouseZoom(e:MouseEvent):void 
		{
			M.distance-=(e.delta)*10
			if(M.distance < M.minZ) M.distance=M.minZ; 	if(M.distance > M.maxZ) M.distance=M.maxZ
			//if(M.moveY)M.baseTarget.y=fix(M.posY-((M.distance-60)*.25))
		}
		public function move(V:Vector3D):void 
		{
			M.baseTarget=V
		}
		public function plan(name:String, speed:Number, V2:Vector3D, height:BitmapData=null, F:Function=null):void{
			if(height)NOIZE=height;
			M['info']=V2 || new Vector3D(50,.5,2048); M.speed=speed; M['planFin']=F || new Function();
			BASE.LOAD.SWF("assets/map/"+name+".swf", ['GROUND'], getmap );
		}
		private function getmap(clip:Array):void{
			var view2d:MovieClip=new clip[0]();
			var Pos:Vector3D= new Vector3D(M.baseTarget.x, M.baseTarget.z, M.speed);
			if(NOIZE)planTop=new map( BASE, view2d, Pos, M.info ,NOIZE );
			else planTop=new map( BASE, view2d, Pos, M.info );
			BASE.stage.addChild(planTop);
			planTop.y=BASE.size.y-90;
			planTop.x=BASE.size.x-120;
			planTop.alpha=1;
			planTop.CamCatch=true;
			M.planFin();
		}
		public function Resize():void
		{
			if(planTop){planTop.y=BASE.size.y-90;planTop.x=BASE.size.x-120;}
			if(!mouseback){ BASE.SYS.viseur.x=BASE.size.x>>1;BASE.SYS.viseur.y=BASE.size.y>>1; }
		}
		//______________________________________Math orbite
		public function Orbit( H:Number=-25, V:Number=90, D:int=20000 ):Vector3D 
		{
			var P:Vector3D=new Vector3D()
			var phi:Number= RadDeg(H)
			var theta:Number= RadDeg(V)
			P.x = fix(D * Math.sin(phi)*Math.cos(theta));
			P.z = fix(D * Math.sin(phi)*Math.sin(theta));
			P.y = fix(D * Math.cos(phi));
			return P;
		}
		public function RadDeg(d:Number):Number{ return(d * (Math.PI / 180)) }
		public function fix(d:Number):Number{ return Number(d.toFixed(3)) }


		public var planTop:map
		private var BASE:Object;
		public var M:Object;
		public var target:*
		public var factor:Number=0
		public var GUN:ObjectContainer3D
		public var GUNin:ObjectContainer3D
		public var mouseback:Boolean=true
		public var NOIZE:BitmapData=null
		//END
	}}